package cn.lic.tool.poi.excel;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFHyperlink;

import cn.lic.tool.poi.excel.function.IValue;
import cn.lic.tool.poi.excel.function.IValue.Type;

public class ParserUtils {
	
//	public static void parseCell(Cell cell, JSONObject params) {
//		if (cell == null || cell.getCellType() != CellType.STRING) {
//			return;
//		}
//		
//		String template = cell.getStringCellValue();
//		if (FunctionParser.isVariable(template)) {
//			/*
//			 * 解析模板变量
//			 * */
//			template = template.substring(2, template.length() - 1);
//			
//			FunctionParser.getFunction(template, params).execute(cell);
//			
//		} else {
//			/*
//			 * 解析普通文本中包含的模板变量
//			 * */
//			StringBuffer sb = new StringBuffer();
//			Pattern pattern = Pattern.compile("\\$\\{[\\w+\\.:@]+\\}");
//			Matcher m = pattern.matcher(template);
//			while(m.find()) {
//				String group = m.group();
//				String key = group.substring(2, group.length() - 1);
//				Object val = null;
//				
//				if (FunctionParser.isFunction(key)) {
//					val = FunctionParser.getFunction(template, params).execute().getResult();
//				} else {
//					val = params.get(key);
//				}
//				m.appendReplacement(sb, String.valueOf(val));
//			}
//			
//			/*
//			 * 如果是常规字符串且没有变量，则不做赋值操作
//			 */
//			if (sb.length() > 0) {
//				m.appendTail(sb);
//				setCellValue(cell, sb);
//			}
//		}
//	}
	
	public static void setCellValue(Cell cell, Object val) {
		POILoggerUtil.info("Set cell Index: " + cell.getAddress() + ": " + cell + "=>" + val);
		if (val == null) {
			cell.setCellValue("");
			cell.setCellType(CellType.BLANK);
			return;
		}
		
		if (val instanceof IValue) {
			val = ((IValue) val).castValue(Type.OBJECT);
			if (val == null) {
				cell.setCellValue("");
				cell.setCellType(CellType.BLANK);
				return;
			}
		}
		
		if (val instanceof Number) {
			Number tmp = (Number)val;
			cell.setCellValue(tmp.doubleValue());
			cell.setCellType(CellType.NUMERIC);
		} else {
			cell.setCellType(CellType.STRING);
			cell.setCellValue(String.valueOf(val));
		}
	}
	
	public static void copyRow(Row srcRow, Row destRow, CellCopyPolicy policy) {
		copyRow(srcRow, destRow, 0, srcRow.getLastCellNum(), policy);
	}

	public static void copyRow(Row srcRow, Row destRow, int cellStartIndex, int cellEndIndex, CellCopyPolicy policy) {
		if (policy == null) {
			policy = new CellCopyPolicy().createBuilder().build();
		}
		for (int i = cellStartIndex; i<= cellEndIndex; i++) {
			Cell srcCell = srcRow.getCell(i);
			 if (srcCell != null) {
				 final Cell destCell = destRow.createCell(srcCell.getColumnIndex(), srcCell.getCellType());
	             copyCell(srcCell, destCell, policy);
			 }
		}

//        final int sheetIndex = _sheet.getWorkbook().getSheetIndex(_sheet);
//        final String sheetName = _sheet.getWorkbook().getSheetName(sheetIndex);
//        final int srcRowNum = srcRow.getRowNum();
//        final int destRowNum = destRow.getRowNum();
//        final int rowDifference = destRowNum - srcRowNum;
//        
//        final FormulaShifter formulaShifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007);
//        final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet);
//        rowShifter.updateRowFormulas(this, formulaShifter);

        // Copy merged regions that are fully contained on the row
        // FIXME: is this something that rowShifter could be doing?
//        if (policy.isCopyMergedRegions()) {
//            for (CellRangeAddress srcRegion : srcRow.getSheet().getMergedRegions()) {
//                if (srcRowNum == srcRegion.getFirstRow() && srcRowNum == srcRegion.getLastRow()) {
//                    CellRangeAddress destRegion = srcRegion.copy();
//                    destRegion.setFirstRow(destRowNum);
//                    destRegion.setLastRow(destRowNum);
//                    getSheet().addMergedRegion(destRegion);
//                }
//            }
//        }

        if (policy.isCopyRowHeight()) {
        	destRow.setHeight(srcRow.getHeight());
        }
    
    
	}
	
	public static void copyCell(Cell srcCell, Cell destCell, CellCopyPolicy policy) {
        // Copy cell value (cell type is updated implicitly)
        if (policy.isCopyCellValue()) {
            if (srcCell != null) {
                CellType copyCellType = srcCell.getCellType();
                if (copyCellType == CellType.FORMULA && !policy.isCopyCellFormula()) {
                    // Copy formula result as value
                    // FIXME: Cached value may be stale
                    copyCellType = srcCell.getCachedFormulaResultType();
                }
                switch (copyCellType) {
                    case NUMERIC:
                        // DataFormat is not copied unless policy.isCopyCellStyle is true
                        if (DateUtil.isCellDateFormatted(srcCell)) {
                        	destCell.setCellValue(srcCell.getDateCellValue());
                        }
                        else {
                        	destCell.setCellValue(srcCell.getNumericCellValue());
                        }
                        break;
                    case STRING:
                    	destCell.setCellValue(srcCell.getStringCellValue());
                        break;
                    case FORMULA:
                    	destCell.setCellFormula(srcCell.getCellFormula());
                        break;
                    case BLANK:
                        break;
                    case BOOLEAN:
                    	destCell.setCellValue(srcCell.getBooleanCellValue());
                        break;
                    case ERROR:
                    	destCell.setCellErrorValue(srcCell.getErrorCellValue());
                        break;

                    default:
                        throw new IllegalArgumentException("Invalid cell type " + srcCell.getCellType());
                }
            }
        }
        
        // Copy CellStyle
        if (policy.isCopyCellStyle()) {
        	destCell.setCellStyle(srcCell == null ? null : srcCell.getCellStyle());
        }
        
        final Hyperlink srcHyperlink = (srcCell == null) ? null : srcCell.getHyperlink();

        if (policy.isMergeHyperlink()) {
            // if srcCell doesn't have a hyperlink and destCell has a hyperlink, don't clear destCell's hyperlink
            if (srcHyperlink != null) {
            	destCell.setHyperlink(new XSSFHyperlink(srcHyperlink));
            }
        } else if (policy.isCopyHyperlink()) {
            // overwrite the hyperlink at dest cell with srcCell's hyperlink
            // if srcCell doesn't have a hyperlink, clear the hyperlink (if one exists) at destCell
        	destCell.setHyperlink(srcHyperlink == null ? null : new XSSFHyperlink(srcHyperlink));
        }
    }
	
}
